En este apartado, se analiza la obra “La Regenta” de Leopoldo Alas Clarín a partir de diferentes técnicas de análisis de contenido. Se tratan, en su mayor parte, de acercamientos estadísticos o cuantitativos a los textos literarios. Por lo tanto, representan una visión limitada de la obra y solo complementaria a la lectura y el análisis cualitativo detenido de la misma.
Nos acercaremos al texto, primero, intentando descubrir cuáles palabras se destacan, sus frecuencias y distribuciones. Luego, analizaremos la obra desde la perspectiva de los personajes, sus relaciones y sus apariciones en la obra.
Las palabras que cuentan
El primer paso del análisis consiste en cargar los datos que hemos preparado en la sección de preparación de los datos y convertirlo en un objeto de tipo corpus. Para ello, emplearemos el paquete de R llamado quanteda, que resulta bastante completo para el análisis de contenido.
El código abajo carga los datos en la memoria, los convierte en un corpus y muestra algunas estadísticas básicas de los capítulos de la obra, como el número de palabras (tokens), el número de palabras únicas (types) y la cantidad de frases.
Code
# carga los datos de "La Regenta"load("../textos/Regenta.RData")# carga el paquete quanteda para # algunos análisislibrary(quanteda)# carga el paquete reactable que# permitirá mostrar los resultados en# una tabla interactivalibrary(reactable)# Elimina el título y el prólogoregc <- regc[3:nrow(regc),]# convierte en un documento corpuscp <-corpus(regc, text_field ="texto")# define los capítulos como nombre# de los documentosdocnames(cp) <- regc$capitulo# muestra estadísticas básicas de# cada capítuloreactable(summary(cp))
Vemos que los treinta capítulos de la obra tienen una extensión que va de poco más de ocho mil hasta aproximadamente veintiún mil palabras. No resulta nada sorprendente que las palabras únicas y el número de frases varíen de forma proporcional.
Frecuencias de palabras
El próximo paso consiste en convertir el corpus en una matriz de términos. Para ello, primero convertimos los textos en tokens, que son las palabras individuales de los textos. Luego, eliminamos las palabras vacías (stopwords) y las palabras que no aportan información, como los números y los signos de puntuación. Este objeto será luego empleado en diversas técnicas de análisis de contenido.
Code
# convierte en tokens y remueve# punctuación, símbolos y númerostk <-tokens(cp, remove_punct =TRUE, remove_numbers =TRUE, remove_symbols =TRUE)# Elimina las palabras vacíastk <-tokens_remove(tk, stopwords("es"))
Para poder explorar cuáles palabras se destacan en la obra podemos emplear una técnica llamada análisis de frecuencia de palabras. En este caso, crearemos una matriz de términos de documentos (document-feature matrix), que es una representación matricial de los textos en la que las filas representan los documentos y las columnas las palabras. Cada celda de la matriz contiene el número de veces que una palabra aparece en un documento.
El código abajo crea la matriz y convierte todos los términos en minúsculas para facilitar el cuenteo. Luego, muestra las cincuenta palabras más frecuentes en la obra.
Code
# convierte en una matriz de términosdtm <-dfm(tk, tolower =TRUE)# muestra las 50 palabras más frecuentestopfeatures(dtm, 50)
don si ana usted magistral aquella aquel álvaro
1789 1164 894 822 767 758 731 488
víctor casa regenta señor vetusta allí ser después
487 477 467 458 455 446 430 415
decía doña vez mesía podía ahora bien ojos
414 411 390 372 368 361 349 346
fermín así iba dos quería dijo siempre menos
345 344 333 330 328 325 325 322
mismo hombre tan vida dios veces quintanar mundo
318 314 312 311 309 305 303 285
mujer todas sabía ver tiempo alma día parecía
284 279 279 279 278 275 271 267
amor aquello
267 265
En este caso, hemos considerado palabras aisladas, pero podemos repetir el análisis con bigramas o trigramas, que son secuencias de dos o tres palabras consecutivas. Estas combinaciones permiten encontrar secuencias de ideas que pueden revelar ciertos contenidos o patrones en el texto.
Code
bi <-tokens_ngrams(tk, n =2)# convierte en una matriz de términosdtm <-dfm(bi)# muestra los 50 bigramas más frecuentestopfeatures(dtm, 50)
¿Qué vemos en los resultados de los bigramas y trigramas? El primer patrón que emerge es la presencia de nombres de personajes, como “don Víctor Quintanar”, “don Álvaro” o “do Fermín”. También aparecen nombres de lugares, como “Vetusta” o “Santa Cruz”. Por último, encontramos algunas secuencias que parecen describir acciones o situaciones, como “señor marqués” o “señor don Fermín”.
Colocaciones
Otro recurso útil a la hora de explorar los términos más frecuentes en un texto proviene de las colocaciones. Las colocaciones son secuencias de palabras que aparecen juntas con más frecuencia de lo que se esperaría por azar. En otras palabras, son secuencias de palabras que tienen un significado especial o que se emplean en un contexto específico.
El código abajo emplea la función textstat_collocations del paquete quanteda.textstats para encontrar las colocaciones más frecuentes en el texto1. En este caso, hemos considerado solo las colocaciones que aparecen al menos diez veces en el texto.
Code
# Carga el paquetelibrary(quanteda.textstats)# Encuentra las colocacionescol <-textstat_collocations(tk, min_count =10)# Muestra los resultadosreactable(col, resizable =TRUE, wrap=F)
Como hemos podido ver, vuelven a aparecer los nombres de los personajes, lugares, pero ahora también llaman la atención algunos términos que indican frecuencia (algunas veces, muchas veces, dos tres, cada día) o hacen referencia al tiempo (aquel momento, aquella tarde, media hora). Estos términos pueden ser útiles para entender el contexto en el que se desarrolla la obra.
Palabras-clave
Otro recurso que disponemos para examinar el contenido de un texto es el análisis de palabras-clave. Podemos interesarnos por un tema o concepto específico y buscar en qué contexto aparece en el texto. En este caso, vamos a buscar la palabra “adulterio” y ver en qué contexto aparece en la obra.
Una estrategia sería ver cuántas veces aparece “adulterio” en la novela, pero eso no nos daría mucha información sobre el contexto en el que se emplea. Por eso, vamos a emplear la función kwic (keyword in context) del paquete quanteda para buscar la palabra en el texto y ver en qué contexto aparece.
El resultado es una tabla que muestra la palabra “adulterio” y las palabras que la rodean en el texto. De esta manera, podemos entender mejor cómo se emplea la palabra en la obra y qué significado tiene en el contexto de la novela.
Code
# Carga el paquetelibrary(quanteda)# recreamos los tokens# sin remover la puntuación# o los stopwordstk <-tokens(cp)# Busca la palabra "adulterio" en# su contextokw_amor <-kwic(tk, pattern ="adulterio")# Muestra los resultadosreactable(kw_amor, resizable =TRUE, wrap=F)
Saltan a la vista los calificativos y acciones que se revelan cuando se analiza el contexto de “adulterio”. Se ven atributos como “repugnante”, “infame”, “ominoso”, “escándalo”. También acciones que se asocian como respuesta al adulterio: “vengar”, “duelo”, “batirme”. En pocas palabras, se nota el rechazo social al adulterio y se puede fácilmente imaginar un desaforado cornudo, pistola en mano, buscando venganza.
Podemos emplear un tipo de visualización de datos llamado árbol de palabras para representar gráficamente el contexto en el que aparece la palabra “adulterio”. En este caso, vamos a emplear la función wordtree del paquete tenet para crear un árbol de palabras que muestre las palabras que aparecen antes y después de “adulterio” en el texto. No obstante, como hemos visto, la palabra “adulterio” no aparece muchas veces en la novela, por lo que el árbol de palabras no será muy complejo ni tampoco interesante. Probemos algo más picantes, que salga el “amor”.
Code
library(tenet)wordtree(cp, "amor")
Ahora las cosas se ponen más interesantes. Vemos que las palabras cambian de tamaño según su frecuencia, de modo que sabemos que “amor de” resulta más común que “amor del”, por ejemplo.
Pero, ¿qué palabras debo elegir? ¿Cómo sé cuáles son las más relevantes? Para responder a estas preguntas, podemos emplear una técnica llamada keyness. Esta técnica compara la frecuencia de una palabra en un texto con su frecuencia en otro texto de referencia. Si la palabra aparece poco en el texto de referencia, entonces debería aparecer poco en el texto elegido. Si no es así, tenemos una palabra clave, entendida como un término cuya frecuencia resulta muy superior a la esperada.
El capítulo 8 de la novela es una delicia para emplear esa técnica. Se trata de un pasaje que contiene la descripción de una merienda en la casa de la marquesa de Vegallana y sus “preparativos” en la cocina. Emplearemos la función textstat_keyness del paquete quanteda.textstats para encontrar las palabras clave.
Code
# Cargamos los paquetes necesarioslibrary(quanteda.textstats)library(quanteda.textplots)# Volvemos a crear los tokens# sin puntos ni stopwords# convierte en tokens y remueve# punctuación, símbolos y númerostk <-tokens(cp, remove_punct =TRUE, remove_numbers =TRUE, remove_symbols =TRUE)# Elimina las palabras vacíastk <-tokens_remove(tk, stopwords("es"))# Creamos la matriz de frecuencia# de términosdtm <-dfm(tk)# Calculamos la estadística, # considerando el capítulo 8 como# objetivo y el resto de la novela# como referenciakey <-textstat_keyness(dtm, target ="08")# Visualizamos los resultadostextplot_keyness(key)
Las palabras asociadas a la comida se destacan: cocina, despensa, cocinero, fogón, pinche, merienda, almíbares. También se destacan palabras asociadas a la nobleza: marques, marquesa, regencia, así como el lugar de las tertulias (el salón amarillo). De otro lado, vemos las palabras que está fuera: Magistral, Fermín, Víctor, Ana, Quintanar, que son personajes que no aparecen en el capítulo 8 o apenas lo hacen.
Podemos añadir información empleando la función plotKeyness del paquete tenet para visualizar los resultados de una manera interactiva y bidimensional. Nos interesa saber, además del chi2, la frecuencia de las palabras. No es lo mismo una palabra rara que aparece poco que otra que no resulta tan común en la obra, pero que se emplea mucho en el capítulo en cuestión.
Code
# carga el paquetelibrary(tenet)# crea el gráficoplotKeyness(cp, ref.cat="08")
De ese modo, las palabras que se encuentren lo más lejos del eje horizontal y vertical serán las más específicas del capítulo. Por otra parte, aquellas que se encuentren más a la derecha, so. las más frecuentes en el capítulo 8. Por lo tanto, términos como “visita”, “cocina”, “marqués” se destacan tanto por su particular incidencia en el capítulo, como por su alta frecuencia. También vemos en rojo las palabras empleadas menos que lo esperado.
Si queremos analizar cuáles son las expresiones de peso en los demás capítulos, basta cambiar el argumento ref.cat por el número del capítulo que nos interese. Estos pasos exploratorios nos permiten tener una idea de los temas y personajes que aparecen en cada capítulo y, por consiguiente, de las palabras clave que los caracterizan.
dicf <-dictionary(list(familia=c("padre", "madre", "hijo", "hija", "hermano", "hermana"),sociedad=c("vetustense","puebl","ciudad","conversa","amig","noble","arist")))plotLexDiv(cp, dicf, title ="La Regenta", subtitle ="Familia y sociedad en la novela", palette = pal$cat.awtools.spalette.6[1:2])
Repetimos el mismo gráfico, ahora con las categorías de tiempo y espacio:
Code
dicf <-dictionary(list(espacio=c("casino","catedral","vivero","casa","espolón","teatro"),tiempo=c("otoño","verano","invierno","primavera","semana santa","navidad")))plotLexDiv(cp, dicf, title ='La Regenta', subtitle ="Espacio y tiempo en la novela", palette = pal$cat.brewer.Dark2.8[c(1:4)])
Code
dicf <-dictionary(list(social=c("casino","teatro","espolón","Paseo de Verano","Paseo de los curas","calle","plaza","tertulia","salon"),religioso=c("catedral","capilla","sacristía","claustro","seminario"), doméstico=c("vivero","\\bcasa\\b","hogar","alcoba","habitación","cama","cocina","despensa")))ft <-filterWords(cp, dicf)ft$name[ft$name!="002 - Prólogo"] <-paste0("Capítulo ",ft$name[ft$name!="002 - Prólogo"])plotSpike(ft, title ='Los espacios de "La Regenta"', subtitle ="Gráfico de dispersión léxica para distintos tipos de espacio.", palette = pal$cat.brewer.Dark2.8[c(1:4)],label.size =3, line.width =0.3, ring.col="black")
dich <-dictionary(list(hombres=list(Alvaro=c("Álvaro Mesía","Álvaro","Mesía","presidente del casino"),Saturnino=c("Saturnino Bermúdez","Saturnino","Bermúdez","Saturno","Saturnillo"),Fermin=c("Magistral","Provisor","Fermín","De Pas","Fermín de Pas","Magistral"),Victor=c("Víctor","Víctor Quintanar","Quintanar"),Otros=c("Agustinito","Amadeo","Anacleto","Anselmo","Antero","Antón Raíces","Antonio","Barcaza","Basilio","Bautista","Bedoya","Belisario","Benítez","Bismark","Campillo","\\b[C]hato\\b","don Carlos","Peláez","Cayetano","Cayetano Ripamilán","Ripamilán","Celedonio","Colás","marqués de Corujedo","Frígilis","Crespo","Custodio","Olías de Cuervo","señor Cuervo","Diego","Escosura","\\b[E]studiante\\b","Pepe","Trabuco","Foja","Fortunato","Francisco de Asís","Francisco de Pas","Francisco de Osuna","Francisco Páez", "señor Páez", "señor de Páez","Francisco Carraspique","Froilán","don Frutos","Frutos Redondo","Fulgosio","Germán","Glocester","Restituto","señor Infanzón", "el Infanzón","Iriarte","Joaquinito","Juanito","Leando","Maroto","marqués de Vegallana","\\s{1}[M]arqués\\b","Martínez","Matías","Matiella","monaguillo","señor Orgaz","\\b[P]alma\\b","Paco","Paquito","Palomo","Rodríguez","Parcerisa","Pedro","\\b[P]erales\\b","Pinón","Pompeyo","Pompeyo Guimarán","Guimarán","Robustiano","señor Roque","Rosendo","don Santos","Sousa","Trifón","\\b[V]inagre\\b","Vinculete") ),mujeres=list(Ana=c("Ana","Anita","Regenta"),Obdulia=c("Obdulia","Obdulia Fandiño","Fandiño","Obdulita"),Otras=c("Agapita","Águeda","Angelina","Anuncita","doña Anuncia","Camila","Carolina","Señora de Infanzón", "la Infanzón","Celestina","Edelmira","Emma","Fabiolita","Fulgencia","Gertrudis","la González","Juana","Lola","doña Lucía","marquesa","Rufina","Olvido","doña Paula","Pepa","Guimarán, Perpétua","\\b[P]ilar\\b","Petra","doña Petronila","Ramona","\\bRita\\b","\\bRosa\\b","Rosita","Rudesinda","Servanda","Társila","\\b[T]eresa\\b","Teresina","Úrsula","Visitación","\\b[V]isita\\b","viuda del marqués de Corujedo") ) ))xp <-countKeywords(cp, dich, rel.freq = F, group.var ="capitulo",quietly =TRUE)# Agrega los resultados por los dos niveles# de código del diccionarioxx <-aggregate(list(frequency=xp$frequency), by=list(groups=xp$groups, level1=xp$level2), sum, na.rm=T)# Elimina los términos no encontrados# en el corpusxx <- xx[xx$frequency>0,]# Ordena por capítuloxx <- xx[order(xx$groups),]plotSankey(xx, from ="level1", to="groups", value ="frequency", opacity =0.05)
# Reorganiza el corpus según# sentencias o frasescs <-corpus_reshape(cp, "sentences")# Calcula la frecuencia en la# que dos codigos del mismo # diccionario aparecen juntos# en cada frased1 <-matchCodes(cs, dic, level =1, quietly=TRUE)# Ordena los resultados de mayor a menord1 <- d1[order(d1$value, decreasing = T),]plotChord(d1, from ="term1", to ="term2", value="value")
Ahora con los personajes
Creamos un diccionario con todos los personajes sin agregar.
Code
# diccionario de personajes# sin agregar en una categoría# otros y otrasdic.per <-dictionary(list(hombres=list(Alvaro=c("Álvaro Mesía","Álvaro","Mesía","presidente del casino"),Saturnino=c("Saturnino Bermúdez","Saturnino","Bermúdez","Saturno","Saturnillo"),Fermin=c("Magistral","Provisor","Fermín","De Pas","Fermín de Pas","Magistral"),Victor=c("Víctor","Víctor Quintanar","Quintanar"),Agustinito="Agustinito",Amadeo="Amadeo",Anacleto="Anacleto",Anselmo="Anselmo",Antero="Antero", Antón="Antón Raíces",Antonio="Antonio",Barcaza="Barcaza",Basilio="Basilio",Bautista="Bautista",Bedoya="Bedoya",Belisario="Belisario", Benítez="Benítez",Bismark="Bismark",Campillo=c("Campillo","\\b[C]hato\\b"),Carlos="Carlos",Pelaez="Peláez",Ripamilan=c("Cayetano","Cayetano Ripamilán","Ripamilán"),Celedonio="Celedonio", Colás="Colás",Corujedo="marqués de Corujedo", Frígilis=c("Frígilis","Crespo"),Custodio=c("Custodio"),Cuervo=c("Olías de Cuervo","señor Cuervo"),Diego="Diego",Escosura="Escosura",Estudiante=c("\\b[E]studiante\\b","Pepe","Trabuco"),Foja="Foja",Fortunato="Fortunato","Francisco de Asís"="Francisco de Asís","Francisco de Pas"="Francisco de Pas","Francisco de Osuma"="Francisco de Osuna", Páez=c("Francisco Páez", "señor Páez", "señor de Páez"),"Francisco Carraspique"="Francisco Carraspique", Froilán="Froilán",Frutos=c("don Frutos","Frutos Redondo"),Fulgosio="Fulgosio", Germán="Germán",Glocester=c("Glocester","Restituto"), Infanzón=c("señor Infanzón", "el Infanzón"),Iriarte="Iriarte",Joaquinito="Joaquinito",Juanito="Juanito",Leandro="Leando",Maroto="Maroto",Vegallana=c("marqués de Vegallana","\\s{1}[M]arqués\\b"), Martínez="Martínez", Matías="Matías",Matiella="Matiella",monaguillo="monaguillo","señor Orgaz"="señor Orgaz",Palma="\\b[P]alma\\b",Paquito=c("Paco","Paquito"),Palomo=c("Palomo","Rodríguez"),Parcerisa="Parcerisa",Pedro="Pedro",Perales="\\b[P]erales\\b", Pinón="Pinón",Pompeyo=c("Pompeyo","Pompeyo Guimarán","Guimarán"),Robustiano="Robustiano",Roque="señor Roque",Rosendo="Rosendo",Santos="don Santos",Sousa="Sousa", Trifón="Trifón",Vinagre="\\b[V]inagre\\b",Vinculete="Vinculete" ),mujeres=list(Ana=c("Ana","Anita","Regenta"),Obdulia=c("Obdulia","Obdulia Fandiño","Fandiño","Obdulita"),Agapita="Agapita", Águeda="Águeda",Angelina="Angelina", Anunciación=c("Anuncita","doña Anuncia"),Camila="Camila",Carolina=c("Carolina","Señora de Infanzón", "la Infanzón"),Celestina="Celestina",Edelmira="Edelmira",Emma="Emma",Fabiolita="Fabiolita",Fulgencia="Fulgencia",Gertrudis="Gertrudis","La González"="la González",Juana="Juana",Lola="Lola", Lucía="doña Lucía",Marquesa=c("marquesa","Rufina"),Olvido="Olvido",Paula="doña Paula",Pepa="Pepa", Perpétua="Guimarán, Perpétua",Pilar="\\b[P]ilar\\b",Petra="Petra",Petrolina="doña Petronila",Ramona="Ramona",Rita="\\bRita\\b",Rosa="\\bRosa\\b",Rosita="Rosita",Rudesinda="Rudesinda",Servanda="Servanda", Társila="Társila",Teresa="\\b[T]eresa\\b",Teresina="Teresina", Úrsula="Úrsula",Visita=c("Visitación","\\b[V]isita\\b"),"Viuda de Corujedo"="viuda del marqués de Corujedo" ) ))
Code
# Emplea el corpus organizado# según párrafoscpp <-corpus(regp, text_field ="texto")# Calcula la frecuencia en la# que dos códigos del mismo # diccionario aparecen juntos# en cada párrafod1 <-matchCodes(cpp, dic.per, level =2, quietly=TRUE)# Ordena los resultados de mayor a menord1 <- d1[order(d1$value, decreasing = T),]# Elimina las asociaciones con Anad1 <- d1[d1$term1!="Ana",]d1 <- d1[d1$term2!="Ana",]# Genera un gráfico de cuerdas# para visualizar las asociacionesplotChord(d1, from ="term1", to ="term2", value="value", elementId ="chord3")
Esta escala se podría interpretar de distintas maneras. Una de ellas es que los capítulos situados más a la izquierda representan una mayor intensidad de la vida social de Vetusta, mientras que aquellos más a la derecha se relacionan con la vida privada, íntima y la infancia de La Regenta.
También podríamos leer los resultados de acuerdo con el protagonismo o mayor centralidad de ciertos personajes según el punto de la escala. Más a la izquierda predominan los Marqueses, Álvaro Mesía (antes de su relación con Ana Ozores) y la sociedad vetustense. En el centro se sitúa Fermín de Pas, que se interpone entre la vida privada de Ana y la vida en sociedad. En la derecha encontramos a Víctor, su esposo, Álvaro (hechos consumados) y en el extremo, la familia de Ana, especialmente en su infancia.
De todas formas, ambas interpretaciones sugieren una dualidad entre la vida íntima y relativamente reservada de Ana en contraste con la vida social y pública de Vetusta. Los dos mundos se tocan en ocasiones concretas por intermedio de algunos actores que transitan dentre ellos, como Fermín de Pas o Álvaro Mesía.
References
Benito Argüelles, Juan. 1984. “Nómina de Personajes de "La Regenta".”Los Cuadernos Del Norte: Revista Cultural de La Caja de Ahorros de Asturias 5 (23): 10–18.
Footnotes
No nos detendremos aquí en explicar los detalles del cálculo de los indicadores. Cada técnica suele estar asociada a un artículo o referencia de ayuda que aclara el algoritmo. Para saber más sobre la función textstat_collocations, puedes consultar la ayuda en R ejecutando el comando help(textstat_collocations) de la consola de R.↩︎